﻿namespace NetFx.SMIL.References
{
  using System;
  using System.Text;
  using System.Collections;
  using System.Collections.Generic;

  using System.Reflection;
  using System.Reflection.Emit;
  using System.Runtime.InteropServices;

  using System.Diagnostics;
  using System.Diagnostics.CodeAnalysis;
  using System.Diagnostics.SymbolStore;
  using System.Security;
  using System.Security.Permissions;

  using NetFx.MSIL;
  using NetFx.SMIL.Definitions;

  /// <summary>
  /// 对象引用。
  /// </summary>
  public class Reference
  {
    #region Statics
    public static Reference it()
    {
      return new Reference();
    }
    public static Reference of(object o)
    {
      if (o == null)
      {
        return NullRef.it();
      }
      else
      {

        Type type = o.GetType();

        if (type.IsValueType)
        {
          return ConstRef.of((ValueType)o);
        }
        else if (type == typeof(string))
        {
          return ConstRef.of(o as string);
        }
        else if (o is MemberInfo)
        {
          return MemberRef.of(o as MemberInfo);
        }
      }
      return it();
    }
    #endregion
    #region Fields
    /// <summary>
    /// 已经引用的对象。
    /// </summary>
    protected object referenced = null;
    #endregion
    #region Properties
    /// <summary>
    /// 获取已经引用的对象。
    /// </summary>
    public virtual object Referenced
    {
      get
      {
        return this.referenced;
      }
    }
    /// <summary>
    /// 判别当前引用是否已经绑定。
    /// </summary>
    public virtual bool IsReferenced
    {
      get
      {
        return this.referenced != null;
      }
    }
    #endregion
    #region Constructors
    public Reference()
    {
      this.referenced = null;
    }
    public Reference(object referenced)
    {
      this.referenced = referenced;
    }
    #endregion
    #region Methods
    public virtual bool IsReferenceOf(object source)
    {
      return object.ReferenceEquals(this.referenced,source) || this.referenced == source;
    }
    public override bool Equals(object obj)
    {
      if (object.ReferenceEquals( obj,this.referenced)) return true;
      if (obj is Reference)
      {
        if ((obj as Reference).Referenced == this.Referenced) return true;
      }
      return false;
    }
    public override int GetHashCode()
    {
      return this.IsReferenced ? this.Referenced.GetHashCode() : base.GetHashCode();
    }
    public override string ToString()
    {
      return this.IsReferenced ? this.Referenced.ToString() : base.ToString();
    }
    #endregion
  }
}
